﻿/* Program.cs - Main program code
 * Part of CalcSharp project.
 * This is Free Software! See GNU GPL for more details
 * CalcSharp (c) 2008 Webmaster442
 */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Text;
using System.Windows.Forms;
using CalcSharp.Core;
using CalcSharp.Core.Containers;
using CalcSharp.Core.IO;
using CalcSharp.Core.Plugin;
using System.Linq;
using CalcSharp.MDIUI;
using CalcSharp.Properties;
using Microsoft.WindowsAPICodePack.Shell;

namespace CalcSharp
{
    partial class Program: IPluginHost, IDisposable
    {
        #region Static Variables
        /// <summary>
        /// command string array
        /// </summary>
        public static string[] cmds;
        /// <summary>
        /// supported commands list
        /// </summary>
        public static string[] supported;
        /// <summary>
        /// calculator mode
        /// </summary>
        public static CalculatorModes mode;
        /// <summary>
        /// if command is a plugin then this string holds it's name
        /// </summary>
        public static string plug;
        /// <summary>
        /// result of the calculation
        /// </summary>
        public static Tresult result;

        public static FunctionManager functionmem;
        // Forms -->
        public static ConsoleFrm ConsoleForm;
        public static HelpDisplay man;
        public static Program loaded;
        public static string Lasterr;
        #endregion

        #region Static Functions, Program Parts
        public static int analize(string str)
        {
            int result = -1;
            result = Array.IndexOf(supported, str.ToUpper());
            if (result == -1)
            {
                var query = loaded.CommandPlugins.FirstOrDefault(cmd => cmd == str.ToUpper());
                if (query != null)
                {
                    result = 0xFFFFFFF;
                    plug = query.ToUpper();
                }
            }
            if (result == -1)
            {
                var query2 = loaded.WindowPlugins.FirstOrDefault(win => win == str.ToUpper());
                if (query2 != null)
                {
                    result = 0xFFFFFFE;
                    plug = query2.ToUpper();
                }
            }
            if (result == -1)
            {
                var query3 = Program.functionmem.keys.FirstOrDefault(funct => funct == str.ToLower());
                if (query3 != null)
                {
                    result = 0xFFFFFFD;
                    plug = query3.ToUpper();
                }
            }
            return result;
        }
        public static void commandlist()
        {
            int lines = Convert.ToInt32(Math.Ceiling((double)Program.supported.Length / 5));
            StringBuilder[] builtinlist = new StringBuilder[lines];
            int i, j = 0;
            List<string> commands = new List<string>(Program.supported);
            commands.Sort();
            string[] documented = man.Documented;
            for (i = 0; i < lines; i++) builtinlist[i] = new StringBuilder();
            for (i = 0; i < supported.Length; i++)
            {
                j++;
                if ((i % lines) == 0) j = 0;
                if (documented.Contains(commands[i].ToLower())) builtinlist[j].AppendFormat(" {0,-15}", commands[i]);
                else builtinlist[j].AppendFormat("*{0,-15}", commands[i]);
            }
            Program.ConsoleForm.ForegroundColor = Color.White;
            for (i = 0; i < lines; i++) Program.ConsoleForm.WriteLine(builtinlist[i].ToString());
            Program.ConsoleForm.ForegroundColor = Color.Gray;
            Program.ConsoleForm.WriteLine("\n Commands available by plugins:");
            Program.ConsoleForm.ForegroundColor = Color.White;
            
            lines = Convert.ToInt32(Math.Ceiling((double)loaded.CMDCount / 5));
            builtinlist = null;
            builtinlist = new StringBuilder[lines];
            for (i = 0; i < lines; i++) builtinlist[i] = new StringBuilder();

            documented = HelpDisplay.GetDocumentedPlugins();
            string[] pluglist = loaded.PluginCommands;

            for (i = 0; i < pluglist.Length; i++)
            {
                j++;
                if ((i % lines) == 0) j = 0;
                if (documented.Contains(pluglist[i])) builtinlist[j].AppendFormat(" {0,-15}", pluglist[i]);
                else builtinlist[j].AppendFormat("*{0,-15}", pluglist[i]);
            }
            for (i = 0; i < lines; i++) Program.ConsoleForm.WriteLine(builtinlist[i].ToString());
            Program.ConsoleForm.ForegroundColor = Color.Gray;
            Program.ConsoleForm.WriteLine("\n Commands available by functions:");
            Program.ConsoleForm.ForegroundColor = Color.White;
            foreach (string ss in Program.functionmem.keys) Program.ConsoleForm.WriteLine(ss);
            documented = null;
            builtinlist = null;
            commands = null;
        }

        [STAThread]
        public static Tresult callfunc(int what, bool reswrite)
        {
            Tresult res = new Tresult();
            ReversePolishNotation rpn = new ReversePolishNotation();
            double temp;
            int limit = cmds.Length;
            ArrayList plugparams = new ArrayList();
            int i;
            try
            {
                switch (what)
                {
                    case 0xFFFFFFF: //plugin command
                        if (cmds.Length > 2 && cmds[cmds.Length - 2].Contains(">") && cmds[cmds.Length - 1] != null) limit = cmds.Length - 2;
                        for (i = 1; i < limit; i++)
                        {
                            try
                            {
                                temp = MiscFuncts.parsestr(cmds[i]);
                                plugparams.Add(temp);
                            }
                            catch
                            {
                                plugparams.Add(cmds[i]);
                            }
                        }
                        res = loaded.GetCMDPluginIface(plug).Run(plugparams);
                        break;
                    case 0xFFFFFFE:
                        if (cmds.Length > 2 && cmds[cmds.Length - 2].Contains(">") && cmds[cmds.Length - 1] != null) limit = cmds.Length - 2;
                        for (i = 1; i < limit; i++)
                        {
                            try
                            {
                                temp = MiscFuncts.parsestr(cmds[i]);
                                plugparams.Add(temp);
                            }
                            catch
                            {
                                plugparams.Add(cmds[i]);
                            }
                        }
                        Form plugin = loaded.GetWindowPluginIface(plug).RunWindow(plugparams);
                        plugin.MdiParent = Program.loaded.parent;
                        plugin.Show();
                        break;
                    case 0xFFFFFFD: //a user function
                        MiscFuncts.calluserfunction(cmds, reswrite);
                        break;
                    case 0: //exit
                        Application.Exit();
                        break;
                    case 1: //add
                        if (mode == CalculatorModes.CPLX) res.complex = CPLXMath.Add(cmds);
                        else res.floatingpt = MathFuncts.add(cmds);
                        break;
                    case 2: //sub
                        if (mode == CalculatorModes.CPLX) res.complex = CPLXMath.Sub(cmds);
                        else res.floatingpt = MathFuncts.sub(cmds);
                        break;
                    case 3: //mul
                        if (mode == CalculatorModes.CPLX) res.complex = CPLXMath.Mul(cmds);
                        else res.floatingpt = MathFuncts.mul(cmds);
                        break;
                    case 4: //div
                        if (mode == CalculatorModes.CPLX) res.complex = CPLXMath.div(cmds);
                        else res.floatingpt = MathFuncts.div(cmds);
                        break;
                    case 5: //clear
                        ConsoleForm.Clear();
                        break;
                    case 6: //echo
                        Program.ConsoleForm.WriteLine(MiscFuncts.echo());
                        break;
                    case 7: //cmdlist
                        Program.ConsoleForm.WriteLine(" Supported Commands ("+Program.supported.Length+"):");
                        Program.ConsoleForm.WriteLine(@" (a * before the name means that the command doesn't have a manual entry)");
                        Program.commandlist();
                        break;
                    case 8: //pow
                        if (mode == CalculatorModes.CPLX) res.complex = CPLXMath.pow(Program.loaded.CPLX_mem[cmds[1]], Program.loaded.CPLX_mem[cmds[2]]);
                        else res.floatingpt = MathFuncts.pow(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 9: //sqr
                        if (mode == CalculatorModes.CPLX) res.complex = CPLXMath.sqr(Program.loaded.CPLX_mem[cmds[1]], Program.loaded.CPLX_mem[cmds[2]]);
                        else res.floatingpt = MathFuncts.sqr(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 10: //sin
                        if (mode == CalculatorModes.CPLX) res.complex = CPLXMath.sin(Program.loaded.CPLX_mem[cmds[1]]);
                        else res.floatingpt = MathFuncts.sin(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 11: //cos
                        if (mode == CalculatorModes.CPLX) res.complex = CPLXMath.cos(Program.loaded.CPLX_mem[cmds[1]]);
                        else res.floatingpt = MathFuncts.cos(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 12: //tan
                        if (mode == CalculatorModes.CPLX) res.complex = CPLXMath.tan(Program.loaded.CPLX_mem[cmds[1]]);
                        else res.floatingpt = MathFuncts.tan(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 13: //ctg
                        if (mode == CalculatorModes.CPLX) res.complex = CPLXMath.ctg(Program.loaded.CPLX_mem[cmds[1]]);
                        else res.floatingpt = MathFuncts.ctg(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 14: //deg2rad
                        res.floatingpt = MathFuncts.deg2rad(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 15: //rad2deg
                        res.floatingpt = MathFuncts.rad2deg(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 16: //mode
                        mode = MiscFuncts.Changemod(MiscFuncts.getstr(cmds[1]));
                        break;
                    case 17: //fact
                        res.floatingpt = MathFuncts.fact(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 18: //arcsin (Program.loaded.CPLX_mem[cmds[1]]);
                        if (mode == CalculatorModes.CPLX) res.complex = CPLXMath.arcsin(Program.loaded.CPLX_mem[cmds[1]]);
                        else res.floatingpt = MathFuncts.arcsin(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 19: //arcccos
                        if (mode == CalculatorModes.CPLX) res.complex = CPLXMath.arccos(Program.loaded.CPLX_mem[cmds[1]]);
                        else res.floatingpt = MathFuncts.arccos(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 20: //arctan
                        if (mode == CalculatorModes.CPLX) res.complex = CPLXMath.arctan(Program.loaded.CPLX_mem[cmds[1]]);
                        else res.floatingpt = MathFuncts.arctan(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 21: //exec
                        ScriptRunner sr = new ScriptRunner(cmds[1]);
                        sr.Run();
                        //res.floatingpt = MiscFuncts.execprg(cmds, false);
                        break;
                    case 22: //forc
                        res = Language.ParseCstyleFor(cmds);
                        break;
                    case 23: //log
                        res.floatingpt = MathFuncts.log(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 24: //prgedit
                        funct_edit defwin;
                        if (cmds.Length > 1) defwin = new funct_edit(cmds[1]);
                        else defwin = new funct_edit();
                        defwin.MdiParent = Program.loaded.parent;
                        defwin.Show();
                        break;
                    case 25: //random
                        res.floatingpt = MathFuncts.random(cmds);
                        break;
                    case 26: //convert
                        res.stringtype = Converter.conv(MiscFuncts.getstr(cmds[1]).ToUpper() , MiscFuncts.getstr(cmds[2]).ToUpper(), MiscFuncts.getstr(cmds[3]));
                        //Program.ConsoleForm.WriteLine(" " + cmds[3] + "(" + cmds[1] + ") = " + tmp + "(" + cmds[2] + ")");
                        break;
                    case 27: //currency
                        Program.ConsoleForm.WriteLine(" Connectig to: http://www.webservicex.net/CurrencyConvertor.asmx ...");
                        Program.ConsoleForm.WriteLine(" Prices are only for information usage.\n Currency rates may change depending on the bank.");
                        currency.CurrencyConvertor conv = new currency.CurrencyConvertor();
                        res.floatingpt = MiscFuncts.parsestr(cmds[1]) * conv.ConversionRate(MiscFuncts.ISOcode2Currenum(cmds[2]), MiscFuncts.ISOcode2Currenum(cmds[3]));
                        break;
                    case 28: //eval
                        rpn.Parse(MiscFuncts.getstr(cmds[1]));
                        res.floatingpt = rpn.Evaluate();
                        break;
                    case 29: //plot
                        ploter.doplot(MiscFuncts.getstr(cmds[1]), MiscFuncts.parsestr(cmds[2]), MiscFuncts.parsestr(cmds[3]), MiscFuncts.parsestr(cmds[4]));
                        break;
                    case 30: //COMB_NOREP
                        res.floatingpt = MathFuncts.combination_norep(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 31: //COMB_REP
                        res.floatingpt = MathFuncts.combination_rep(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 32: //VAR_NOREP
                        res.floatingpt = MathFuncts.variation_norep(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 33: //percent
                        res.floatingpt = MathFuncts.percent(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 34: //apercent
                        res.floatingpt = MathFuncts.apercent(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 35: //isprime
                        res.floatingpt = MathFuncts.isprime(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 36: //gcd
                        res.floatingpt = MathFuncts.gcd(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 37: //lcm
                        res.floatingpt = MathFuncts.lcm(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 38: //help
                        Program.man.Dispose();
                        Program.man = new HelpDisplay();
                        Program.man.MdiParent = loaded.parent;
                        if (cmds[1] != null) Program.man.DisplayCommandHelp(cmds[1]);
                        break;
                    case 39: //quadeq
                        MathFuncts.quadratic_equation(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]), MiscFuncts.parsestr(cmds[3]));
                        break;
                    case 40: //b_and
                        if (loaded.set_mem.isset(cmds[1])) res.settype = Logic.AND(loaded.set_mem[cmds[1]], loaded.set_mem[cmds[2]]);
                        else if (loaded.mtrx_mem.isset(cmds[1])) res.matrixtype = Logic.AND(loaded.mtrx_mem[cmds[1]], loaded.mtrx_mem[cmds[2]]);
                        else res.floatingpt = Logic.AND(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 41: //b_or
                        if (loaded.set_mem.isset(cmds[1])) res.settype = Logic.OR(loaded.set_mem[cmds[1]], loaded.set_mem[cmds[2]]);
                        else if (loaded.mtrx_mem.isset(cmds[1])) res.matrixtype = Logic.OR(loaded.mtrx_mem[cmds[1]], loaded.mtrx_mem[cmds[2]]);
                        else res.floatingpt = Logic.OR(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 42: //b_not
                        if (loaded.set_mem.isset(cmds[1])) res.settype = Logic.NOT(loaded.set_mem[cmds[1]]);
                        else if (loaded.mtrx_mem.isset(cmds[1])) res.matrixtype = Logic.NOT(loaded.mtrx_mem[cmds[1]]);
                        else res.floatingpt = Logic.NOT(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 43: //b_eq
                        if (loaded.set_mem.isset(cmds[1])) res.settype = Logic.EQ(loaded.set_mem[cmds[1]], loaded.set_mem[cmds[2]]);
                        else if (loaded.mtrx_mem.isset(cmds[1])) res.matrixtype = Logic.EQ(loaded.mtrx_mem[cmds[1]], loaded.mtrx_mem[cmds[2]]);
                        else res.floatingpt = Logic.EQ(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 44: //b_xor
                        if (loaded.set_mem.isset(cmds[1])) res.settype = Logic.XOR(loaded.set_mem[cmds[1]], loaded.set_mem[cmds[2]]);
                        else if (loaded.mtrx_mem.isset(cmds[1])) res.matrixtype = Logic.XOR(loaded.mtrx_mem[cmds[1]], loaded.mtrx_mem[cmds[2]]);
                        else res.floatingpt = Logic.XOR(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 45: //b_nand
                        if (loaded.set_mem.isset(cmds[1])) res.settype = Logic.NAND(loaded.set_mem[cmds[1]], loaded.set_mem[cmds[2]]);
                        else if (loaded.mtrx_mem.isset(cmds[1])) res.matrixtype = Logic.NAND(loaded.mtrx_mem[cmds[1]], loaded.mtrx_mem[cmds[2]]);
                        else res.floatingpt = Logic.NAND(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 46: //b_nor
                        if (loaded.set_mem.isset(cmds[1])) res.settype = Logic.NOR(loaded.set_mem[cmds[1]], loaded.set_mem[cmds[2]]);
                        else if (loaded.mtrx_mem.isset(cmds[1])) res.matrixtype = Logic.NOR(loaded.mtrx_mem[cmds[1]], loaded.mtrx_mem[cmds[2]]);
                        else res.floatingpt = Logic.NOR(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 47: //chcode
                        res.floatingpt = MiscFuncts.chartoUTFnum(cmds[1][0]);
                        break;
                    case 48: //set_push
                        SetFuncts.ApendToSet(cmds[1], Program.loaded.set_mem[cmds[2]]);
                        break;
                    case 49: //set_max
                        res.floatingpt = Program.loaded.Set_mem[cmds[1]].StatMax();
                        break;
                    case 50: //set_min
                        res.floatingpt = Program.loaded.Set_mem[cmds[1]].StatMin();
                        break;
                    case 51: //set_count
                        res.floatingpt = Program.loaded.Set_mem[cmds[1]].Count;
                        break;
                    case 52: //set_sum
                        res.floatingpt = Program.loaded.Set_mem[cmds[1]].StatSum();
                        break;
                    case 53: //set_avg
                        avgtype t = avgtype.normal;
                        if (MiscFuncts.getstr(cmds[2]).ToUpper() == "NORMAL" || MiscFuncts.getstr(cmds[2]).ToUpper() == "N") t = avgtype.normal;
                        else if (MiscFuncts.getstr(cmds[2]).ToUpper() == "GEOMETRIC" || MiscFuncts.getstr(cmds[2]).ToUpper() == "G") t = avgtype.mertani;
                        else if (MiscFuncts.getstr(cmds[2]).ToUpper() == "HARMONIC" || MiscFuncts.getstr(cmds[2]).ToUpper() == "H") t = avgtype.harmonic;
                        else if (MiscFuncts.getstr(cmds[2]).ToUpper() == "SQUARE" || MiscFuncts.getstr(cmds[2]).ToUpper() == "S") t = avgtype.square;
                        else throw new CSException("Invalid average type. Type can be normal, geometric, harmonic or square");
                        res.floatingpt = Program.loaded.Set_mem[cmds[1]].StatAvg(t);
                        break;
                    case 54: //set_median
                        res.floatingpt = Program.loaded.Set_mem[cmds[1]].StatMedian();
                        break;
                    case 55: //set_modus
                        res.floatingpt = Program.loaded.Set_mem[cmds[1]].StatModus();
                        break;
                    case 56: //set_deviat
                        deviattype dt = deviattype.normal;
                        if (MiscFuncts.getstr(cmds[2]).ToUpper() == "NORMAL" || cmds[2].ToUpper() == "N") dt = deviattype.normal;
                        else if (MiscFuncts.getstr(cmds[2]).ToUpper() == "CORIGATED" || cmds[2].ToUpper() == "C") dt = deviattype.corigated;
                        res.floatingpt = Program.loaded.Set_mem[cmds[1]].StatDeviat(dt);
                        break;
                    case 57: //set_range
                        res.floatingpt = Program.loaded.Set_mem[cmds[1]].Stat_Range();
                        break;
                    case 58: //stat_plot
                        ploter.plot_data(cmds);
                        break;
                    case 59: //set_descartes
                        res.matrixtype = MatrixFuncts.Descartes(Program.loaded.set_mem[cmds[1]], Program.loaded.set_mem[cmds[2]]);
                        break;
                    case 60: //mtrx_det
                        res.floatingpt = loaded.Mtrx_mem[cmds[1]].Determinant();
                        break;
                    case 61: //mtrx_add
                        if (Program.loaded.Mtrx_mem.StorageType == MtrxStorageType.tdouble) res.matrixtype = (DoubleMatrix)loaded.Mtrx_mem[cmds[1]] + (DoubleMatrix)loaded.Mtrx_mem[cmds[2]];
                        else if (Program.loaded.mtrx_mem.StorageType == MtrxStorageType.tfloat) res.matrixtype = (FloatMatrix)loaded.Mtrx_mem[cmds[1]] + (FloatMatrix)loaded.Mtrx_mem[cmds[2]];
                        else res.matrixtype = (Int24Matrix)loaded.Mtrx_mem[cmds[1]] + (Int24Matrix)loaded.Mtrx_mem[cmds[2]];
                        break;
                    case 62: //mtrx_sub
                        if (Program.loaded.Mtrx_mem.StorageType == MtrxStorageType.tdouble) res.matrixtype = (DoubleMatrix)loaded.Mtrx_mem[cmds[1]] - (DoubleMatrix)loaded.Mtrx_mem[cmds[2]];
                        else if (Program.loaded.mtrx_mem.StorageType == MtrxStorageType.tfloat) res.matrixtype = (FloatMatrix)loaded.Mtrx_mem[cmds[1]] - (FloatMatrix)loaded.Mtrx_mem[cmds[2]];
                        else res.matrixtype = (Int24Matrix)loaded.Mtrx_mem[cmds[1]] - (Int24Matrix)loaded.Mtrx_mem[cmds[2]];
                        break;
                    case 63: //mtrx_mul
                        if (Program.loaded.Mtrx_mem.StorageType == MtrxStorageType.tdouble) res.matrixtype = (DoubleMatrix)loaded.Mtrx_mem[cmds[1]] * (DoubleMatrix)loaded.Mtrx_mem[cmds[2]];
                        else if (Program.loaded.mtrx_mem.StorageType == MtrxStorageType.tfloat) res.matrixtype = (FloatMatrix)loaded.Mtrx_mem[cmds[1]] * (FloatMatrix)loaded.Mtrx_mem[cmds[2]];
                        else res.matrixtype = (Int24Matrix)loaded.Mtrx_mem[cmds[1]] * (Int24Matrix)loaded.Mtrx_mem[cmds[2]];
                        break;
                    case 64: //mtrx_neg
                        if (Program.loaded.mtrx_mem.StorageType == MtrxStorageType.tdouble) res.matrixtype = new DoubleMatrix((DoubleMatrix)loaded.Mtrx_mem[cmds[1]]);
                        else if (Program.loaded.mtrx_mem.StorageType == MtrxStorageType.tfloat) res.matrixtype = new FloatMatrix((FloatMatrix)loaded.Mtrx_mem[cmds[1]]);
                        else res.matrixtype = new Int24Matrix((Int24Matrix)loaded.Mtrx_mem[cmds[1]]);
                        res.matrixtype.Negate();
                        break;
                    case 65: //mtrx_inv
                        if (Program.loaded.Mtrx_mem.StorageType == MtrxStorageType.tdouble) res.matrixtype = (DoubleMatrix)loaded.Mtrx_mem[cmds[1]].Inverse();
                        else if (Program.loaded.Mtrx_mem.StorageType == MtrxStorageType.tfloat) res.matrixtype = (FloatMatrix)loaded.Mtrx_mem[cmds[1]].Inverse();
                        else res.matrixtype = (Int24Matrix)loaded.Mtrx_mem[cmds[1]].Inverse();
                        break;
                    case 66: //mtrx_trnsf
                        res.matrixtype = MatrixFuncts.matrix_transform(loaded.Mtrx_mem[cmds[1]], cmds[2]);
                        break;
                    case 67: //fibonacci
                        res.floatingpt = MathFuncts.fibonacci(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 68: //round
                        res.floatingpt = Math.Round(MiscFuncts.parsestr(cmds[1]), Convert.ToInt32(MiscFuncts.parsestr(cmds[2])));
                        break;
                    case 69: //MTRX_TRNSPS
                        if (Program.loaded.Mtrx_mem.StorageType == MtrxStorageType.tdouble) res.matrixtype = (DoubleMatrix)loaded.Mtrx_mem[cmds[1]].Transpose();
                        else if (Program.loaded.Mtrx_mem.StorageType == MtrxStorageType.tfloat) res.matrixtype = (FloatMatrix)loaded.Mtrx_mem[cmds[1]].Transpose();
                        else res.matrixtype = (Int24Matrix)loaded.Mtrx_mem[cmds[1]].Transpose();
                        break;
                    case 70: //save
                        LoadSaveUI.Save(cmds);
                        break;
                    case 71: //MTRX_EDIT
                        MatrixEditor med;
                        if (cmds.Length > 1) med = new MatrixEditor(cmds[1]);
                        else med = new MatrixEditor();
                        med.MdiParent = loaded.parent;
                        med.Show();
                        break;
                    case 72: //sign
                        res.floatingpt = MathFuncts.sign(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 73: //mod
                        res.floatingpt = res.floatingpt = MathFuncts.mod(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 74: //MTRX_LOADF
                        LoadSaveUI.Load(cmds);
                        break;
                    case 75: //deg2grad
                        res.floatingpt = MathFuncts.deg2grad(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 76: //grad2deg
                        res.floatingpt = MathFuncts.grad2deg(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 77: //mem_mov
                        mem_man.MOV(cmds[1], cmds[2]);
                        break;
                    case 78: //mem_rem
                        mem_man.Remove(cmds[1]);
                        break;
                    case 79: //mem_clr
                        mem_man.ClearAll(cmds[1]);
                        break;
                    case 80: //SET_UNION
                        res.settype = SetFuncts.AplyOperation(Program.loaded.set_mem[cmds[1]], Program.loaded.set_mem[cmds[2]], "+"); 
                        break;
                    case 81: //SET_SECTION
                        res.settype = SetFuncts.AplyOperation(Program.loaded.set_mem[cmds[1]], Program.loaded.set_mem[cmds[2]], "*"); 
                        break;
                    case 82: //SET_Dif
                        res.settype = SetFuncts.AplyOperation(Program.loaded.set_mem[cmds[1]], Program.loaded.set_mem[cmds[2]], "/"); 
                        break;
                    case 83: //b_shl
                        if (loaded.set_mem.isset(cmds[1])) res.settype = Logic.SHL(loaded.set_mem[cmds[1]], MiscFuncts.parsestr(cmds[2]));
                        else if (loaded.mtrx_mem.isset(cmds[1])) res.matrixtype = Logic.SHL(loaded.mtrx_mem[cmds[1]], MiscFuncts.parsestr(cmds[2]));
                        else res.floatingpt = Logic.SHL(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 84: //b_shr
                        if (loaded.set_mem.isset(cmds[1])) res.settype = Logic.SHR(loaded.set_mem[cmds[1]], MiscFuncts.parsestr(cmds[2]));
                        else if (loaded.mtrx_mem.isset(cmds[1])) res.matrixtype = Logic.SHR(loaded.mtrx_mem[cmds[1]], MiscFuncts.parsestr(cmds[2]));
                        else res.floatingpt = Logic.SHR(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 85: //sinh
                        res.floatingpt = MathFuncts.sinh(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 86: //cosh
                        res.floatingpt = MathFuncts.cosh(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 87: //tanh
                        res.floatingpt = MathFuncts.tanh(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 88:
                        Program.loaded.SerializeMem(MiscFuncts.getstr(cmds[1]));
                        break;
                    case 89:
                        Program.loaded.DeSerializeMem(MiscFuncts.getstr(cmds[1]));
                        break;
                    case 90:
                        MatrixUI.SwitchMatrixStorage(cmds[1]);
                        break;
                    case 91:
                        res.matrixtype = MatrixUI.geotrnsf(cmds);
                        break;
                    case 92:
                        res = Language.ParseIF(cmds);
                        break;
                    case 93:
                        res = Language.ParseFor(cmds);
                        break;
                    case 94:
                        res.floatingpt = MathFuncts.arcsinh(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 95:
                        res.floatingpt = MathFuncts.arccosh(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 96:
                        res.floatingpt = MathFuncts.arctanh(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 97:
                        res.floatingpt = MathFuncts.integral(MiscFuncts.getstr(cmds[1]), MiscFuncts.parsestr(cmds[2]), MiscFuncts.parsestr(cmds[3]));
                        break;
                    case 98:
                        Program.ConsoleForm.WriteLine(" Numerical integration result may differ from symbolical result.");
                        res.floatingpt = MathFuncts.derive(MiscFuncts.getstr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 99:
                        res.settype = Program.loaded.set_mem[cmds[1]].Sort();
                        break;
                    case 100:
                        res.settype = Program.loaded.set_mem[cmds[1]].Reverse();
                        break;
                    case 101:
                        res.settype = Program.loaded.set_mem[cmds[1]].Unique();
                        break;
                    case 102:
                        res = Language.ParseForeach(cmds);
                        break;
                    case 103:
                        seteditor sed;
                        if (cmds.Length > 1) sed = new seteditor(cmds[1]);
                        else sed = new seteditor();
                        sed.MdiParent = loaded.parent;
                        sed.Show();
                        break;
                    case 104:
                        res.complex = MatrixFuncts.Mtrx_dim(Program.loaded.mtrx_mem[cmds[1]]);
                        break;
                    case 105:
                        res.floatingpt = mem_man.size(cmds[1]);
                        break;
                    case 106:
                        res.settype = Program.loaded.set_mem[cmds[1]].Randomize();
                        break;
                    case 107:
                        res.matrixtype = MatrixFuncts.CalculateHistogram(Program.loaded.mtrx_mem[cmds[1]]);
                        break;
                    case 108:
                        if (Program.loaded.cplx_mem.isset(cmds[1])) res.floatingpt = CPLXMath.Abs(Program.loaded.cplx_mem[cmds[1]]);
                        else res.floatingpt = Math.Abs(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 109:
                        res.floatingpt = MiscFuncts.parsestr(MiscFuncts.getstr(cmds[1]));
                        break;
                    case 110:
                        res.stringtype = MiscFuncts.parsestr(cmds[1]).ToString();
                        break;
                    case 111:
                        TimerUI.TimerSet(cmds);
                        break;
                    case 112:
                        TimerUI.TimerStrart(cmds);
                        break;
                    case 113:
                        TimerUI.TimerStop(cmds);
                        break;
                    case 114:
                        TimerUI.ClearTimer(cmds);
                        break;
                    case 115:
                        if (loaded.set_mem.isset(cmds[1])) res.settype = Logic.BitCount(loaded.set_mem[cmds[1]]);
                        else if (loaded.mtrx_mem.isset(cmds[1])) res.matrixtype = Logic.BitCount(loaded.mtrx_mem[cmds[1]]);
                        else res.floatingpt = Logic.BitCount(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 116:
                        res.floatingpt = MathFuncts.gamma(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 117:
                        res.floatingpt = MathFuncts.beta(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]));
                        break;
                    case 118:
                        res.floatingpt = MathFuncts.digamma(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 119:
                        res.floatingpt = MathFuncts.harmonic(MiscFuncts.parsestr(cmds[1]));
                        break;
                    case 120:
                        res.stringtype = MathFuncts.Viete(MiscFuncts.parsestr(cmds[1]), MiscFuncts.parsestr(cmds[2]), MiscFuncts.parsestr(cmds[3]));
                        break;
                }
                if (cmds.Length - 2 > 0)
                {
                    if (cmds[cmds.Length - 2] == ">" && cmds[cmds.Length - 1] != null) mem_man.StoreTres(res, cmds[cmds.Length - 1], storeoption.copy);
                    else if (cmds[cmds.Length - 2] == "*>" && cmds[cmds.Length - 1] != null) mem_man.StoreTres(res, cmds[cmds.Length - 1], storeoption.mul);
                    else if (cmds[cmds.Length - 2] == "+>" && cmds[cmds.Length - 1] != null) mem_man.StoreTres(res, cmds[cmds.Length - 1], storeoption.add);
                    else if (cmds[cmds.Length - 2] == "->" && cmds[cmds.Length - 1] != null) mem_man.StoreTres(res, cmds[cmds.Length - 1], storeoption.sub);
                    else if (cmds[cmds.Length - 2] == "/>" && cmds[cmds.Length - 1] != null) mem_man.StoreTres(res, cmds[cmds.Length - 1], storeoption.div);
                }
                Lasterr = null;
                GC.Collect();
            }
            catch (Exception Ex)
            {
                Program.ConsoleForm.ForegroundColor = Settings.Default.console_warn;
                if (Ex is IndexOutOfRangeException || Ex is ArgumentOutOfRangeException) Program.ConsoleForm.WriteLine(" Not enough parameters.");
                else if (Ex is CSException) Program.ConsoleForm.WriteLine(" An error occured:\n  " + Ex.Message);
                else if (Ex is IOException) Program.ConsoleForm.WriteLine(" I/O error: " + Ex.Message);
                else if (Ex is OutOfMemoryException) Program.ConsoleForm.WriteLine(" Not enough memory to complete operation");
                else if (Ex is NotImplementedException) Program.ConsoleForm.WriteLine(" This Function is not yet implemented");
                else
                {
                    Program.ConsoleForm.ForegroundColor = Settings.Default.console_err;
                    Program.ConsoleForm.WriteLine(" An exception occured:\n  " + Ex.Message + " Source: " + Ex.TargetSite.ToString());
                }
                Program.ConsoleForm.ForegroundColor = Settings.Default.console_color;
                Program.loaded.parent.AnimateProgress(false);
            }
            return res;
        }
        #endregion

        #region Main function
        [STAThread]
        static void Main(string[] args)
        {
            if (CoreInit.IntializeCore())
            {
                ConstCommands.LoadCommands(); //Első!!! muszály!!!
                result = new Tresult();
                loaded = new Program(FileHelper.Appdir);
                ConsoleForm = new ConsoleFrm(); //konzo
                man = new HelpDisplay();
                Application.EnableVisualStyles();
                mode = 0; //deg
                functionmem = new FunctionManager();
                if (File.Exists(FileHelper.ProfileDir + @"\CalcSharpUserData\resrume.dat"))
                {
                    try
                    {
                        loaded.DeSerializeMem(FileHelper.ProfileDir + @"\CalcSharpUserData\resrume.dat");
                    }
                    catch (Exception) { }
                }
                Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);
                Application.Run(loaded.Parent);
                loaded = null; //destrukt
                GC.Collect();
            }
            else CoreInit.ErrorMesage();
        }

        static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)
        {
            MessageBox.Show(e.Exception.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        #endregion
    }
}
